<?php

namespace App\Http\Controllers\Api;

use App\V3\Api\Models\AdminAddendumModel;
use App\Api\Models\LogOutStorageModel;
use App\Api\Models\SellGoodsDetailModel;
use App\Api\Models\SellModel;
use App\Api\Models\StorageBatchModel;
use App\V3\Api\Models\StorageShelfLocationModel;
use App\V3\Api\Models\StorageShelfModel;
use App\V3\Api\Models\VipSettingModel;
use App\Http\Controllers\Controller;
use App\V3\V3_1\Models\LogInStorageModel;
use App\V3\V3_1\Models\OperationLogModel;
use App\V3\V3_1\Models\PackageContentModel;
use App\V3\V3_1\Models\PackageModel;
use App\V3\V3_1\Models\PackageOldModel;
use App\V3\V3_1\Models\SalesReturnModel;
use App\V3\V3_1\Models\SerialNumberModel;
use App\V3\V3_1\Models\SupplierCustomerModel;
use App\V3\V3_2\Models\AdminPermissionLimitModel;
use App\V3\V3_2\Models\ModuleModel;
use Illuminate\Support\Facades\Log;
use App\V3\V3_1\Models\StorageManageModel;
use App\V3\V3_1\Models\MaterielClassModel;
use Illuminate\Support\Facades\DB;
use App\V3\V3_1\Models\MaterielTypeModel;
use App\V3\V3_1\Models\MaterielModel;
use App\V3\V3_1\Models\StorageModel;
use Illuminate\Http\Request;
use App\V3\V3_1\Models\AdminModel;
use App\V3\V3_1\Models\UserModel;
use Illuminate\Support\Facades\Storage;
use OSS\OssClient;
use App\V3\Api\Models\StorageSpaceOrderModel;

class SyncDataController extends Controller
{
    protected $ossClient;

    public function __construct(Request $request)
    {
        $this->ossClient = new OssClient(
            config('app.aliyun_oss_key'),
            config('app.aliyun_oss_secret'),
            config('app.aliyun_oss_endpoint'),
        );
    }

    public function syncData()
    {
        SELF::SyncAccount();
        SELF::syncStorageManage();
        SELF::SyncStorageManager();
        SELF::SyncMateriel();

        return 1;
    }

    //账号同步
    public function SyncAccount()
    {
        DB::beginTransaction();
        try {
            $adminInfo = AdminModel::select('id', 'username')->where('parent_id', 0)->orderBy('id', 'ASC')->get();

            $adminId = [];
            foreach ($adminInfo as $key => $value) {
                $adminId[] = $value['id'];
                AdminModel::where('id', $value['id'])->update(['mobile' => $value['username']]);
            }

            $userInfo = UserModel::whereIn('main_id', $adminId)->where('delete_flag', 0)->get();

            $arr = [];
            foreach ($userInfo as $k => $v) {
                $arr[$k]['id'] = $v['id'];
                $arr[$k]['username'] = $v['username'];
                $arr[$k]['password'] = $v['password'];
                $arr[$k]['nickname'] = $v['nickname'];
                $arr[$k]['mobile'] = empty($v['mobile']) ? '' : $v['mobile'];
                $arr[$k]['parent_id'] = $v['main_id'];
                $arr[$k]['first_module'] = '61';
                $arr[$k]['second_module'] = '63,64,66,67';
                $arr[$k]['is_active'] = $v['is_active'];
            }

            foreach ($arr as $kk => $val) {
                $userId = $val['id'];
                unset($val['id']);

                $id = AdminModel::insertGetId($val);

                UserModel::where('id', $userId)->update(['new_id' => $id]);
            }

            DB::commit();
            return true;
        } catch (\Exception $e) {
            DB::rollback();
            Log::debug('sync_account' . var_export($e->getMessage(), true));
            return false;
        }
    }

    //仓库管理人信息同步
    public function SyncStorageManager()
    {
        DB::beginTransaction();

        try {
            $userInfo = UserModel::select('id', 'new_id')->where('delete_flag', 0)->get();
            $storageInfo = StorageModel::get();

            $storage = [];
            foreach ($storageInfo as $key => $value) {
                $storage[] = [
                    'id' => $value['id'],
                    'user_id' => $value['user_id']
                ];
            }

            $user = SELF::userInfo();

            $arr = [];
            foreach ($storage as $k1 => $v1) {
                foreach ($user as $k2 => $v2) {
                    if ($v1['user_id'] == $v2['id']) {
                        $arr[] = [
                            'id' => $v1['id'],
                            'user_id' => $v2['new_id']
                        ];
                    }
                }
            }

            foreach ($arr as $k3 => $v3) {
                StorageModel::where('id', $v3['id'])->update(['user_id' => $v3['user_id']]);
            }

            DB::commit();
            return true;
        } catch (\Exception $e) {
            DB::rollback();
            Log::debug('sync_storage' . var_export($e->getMessage(), true));
        }
    }

    //同步采购单信息
    public function SyncMateriel()
    {
        DB::beginTransaction();

        try {
            $materielInfo = MaterielModel::get();

            $materiel = [];
            foreach ($materielInfo as $key => $value) {
                $materiel[] = [
                    'id' => $value['id'],
                    'user_id' => $value['user_id']
                ];
            }

            $user = SELF::userInfo();

            $arr = [];
            foreach ($materiel as $k1 => $v1) {
                foreach ($user as $k2 => $v2) {
                    if ($v1['user_id'] == $v2['id']) {
                        $arr[] = [
                            'id' => $v1['id'],
                            'user_id' => $v2['new_id']
                        ];
                    }
                }
            }

            foreach ($arr as $k3 => $v3) {
                MaterielModel::where('id', $v3['id'])->update(['user_id' => $v3['user_id']]);
            }
            DB::commit();
            return true;
        } catch (\Exception $e) {
            DB::rollback();
            Log::debug('sync_storage' . var_export($e->getMessage(), true));
        }
    }

    //同步库存信息
    public function syncStorageManage()
    {
        DB::beginTransaction();
        try {
            $stoarageManageInfo = StorageManageModel::where('delete_flag', 0)->where('main_id', 7)->get()->toArray();


            $classId = [];
            $typeId = [];
            $storageId = [];
            foreach ($stoarageManageInfo as $key => $value) {
                $classId[] = $value['materiel_class_id'];
                $typeId[] = $value['type_id'];
                $storageId[] = $value['storage_id'];
            }

            $classInfo = MaterielClassModel::whereIn('id', array_unique($classId))->get()->toArray();
            $typeInfo = MaterielTypeModel::whereIn('id', array_unique($typeId))->get()->toArray();
            $storageInfo = StorageModel::whereIn('id', array_unique($storageId))->get()->toArray();

            foreach ($stoarageManageInfo as $k1 => $v1) {
                foreach ($classInfo as $k2 => $v2) {
                    if ($v1['materiel_class_id'] == $v2['id']) {
                        $stoarageManageInfo[$k1]['materiel_class_name'] = $v2['class_name'];
                        $stoarageManageInfo[$k1]['materiel_class_no'] = $v2['class_no'];
                    }
                }

                foreach ($typeInfo as $k3 => $v3) {
                    if ($v1['type_id'] == $v3['id']) {
                        $stoarageManageInfo[$k1]['materiel_name'] = $v3['materiel_name'];
                        $stoarageManageInfo[$k1]['type_name'] = $v3['type_name'];
                        $stoarageManageInfo[$k1]['materiel_no'] = $v3['materiel_no'];
                    }
                }

                foreach ($storageInfo as $k4 => $v4) {
                    if ($v1['storage_id'] == $v4['id']) {
                        $stoarageManageInfo[$k1]['storage_name'] = $v4['storage_name'];
                        $stoarageManageInfo[$k1]['storage_address'] = $v4['storage_address'];
                    }
                }
            }

            foreach ($stoarageManageInfo as $v5) {
                StorageManageModel::where('id', $v5['id'])
                    ->update($v5);
            }
            // StorageManageModel::update($stoarageManageInfo);
            DB::commit();
            return true;
        } catch (\Exception $e) {
            DB::rollback();
            Log::debug(var_export($e->getMessage(), true));
        }
    }

    private function userInfo()
    {
        $userInfo = UserModel::select('id', 'new_id')->where('delete_flag', 0)->get();

        $user = [];
        foreach ($userInfo as $k => $val) {
            $user[] = [
                'id' => $val['id'],
                'new_id' => $val['new_id']
            ];
        }

        return $user;
    }

    public function SyncPackage()
    {
        DB::beginTransaction();

        try {
            DB::enableQueryLog();
            $data = PackageOldModel::where(function ($query) {
                $query->whereNotNull('package_content');
                $query->where('package_content', '!=', 'a:0:{}');
            }
            )
                ->where('delete_flag', 0)->get()->toArray();

            foreach ($data as $key => $v) {
                $data[$key]['package_content'] = unserialize($v['package_content']);
            }

            foreach ($data as $k1 => $v1) {
                foreach ($v1['package_content'] as $k2 => $v2) {
                    $data[$k1]['package_content'][$k2]['old_id'] = $v1['id'];
                }
            }

            foreach ($data as $v2) {
                $insertId = PackageModel::insertGetId([
                    'package_name' => $v2['package_name'],
                    'main_id' => $v2['main_id'],
                    'created_at' => time(),
                ]);

                foreach ($v2['package_content'] as $v3) {
                    if ($v2['id'] == $v3['old_id']) {
                        $storageManageInfo = StorageManageModel::select(
                            'c.id as materiel_first_class_id',
                            'c.class_name as materiel_first_class_name',
                            'c.class_no as materiel_first_class_no',
                            'b.id as materiel_class_id',
                            'b.class_name as materiel_class_name',
                            'b.class_no as materiel_class_no',
                            'd.id as type_id',
                            'd.materiel_name as materiel_name',
                            'd.type_name as type_name',
                            'd.materiel_no as materiel_no',
                            'a.storage_id',
                            'a.storage_name',
                            'a.storage_address',
                            'a.id as storage_manage_id'
                        )
                            ->from('storage_manage as a')
                            ->leftJoin('materiel_class as b', 'b.id', '=', 'a.materiel_class_id')
                            ->leftJoin('materiel_class as c', 'c.id', '=', 'b.parent_id')
                            ->leftJoin('materiel_type as d', 'd.id', '=', 'a.type_id')
                            ->leftJoin('storage as e', 'e.id', '=', 'a.storage_id')
                            ->where('a.id', $v3['id'])->first();

                        if (!empty($storageManageInfo)) {
                            PackageContentModel::insert([
                                'main_id' => $v2['main_id'],
                                'package_id' => $insertId,
                                'created_at' => time(),
                                'materiel_first_class_id' => $storageManageInfo['materiel_first_class_id'],
                                'materiel_first_class_name' => $storageManageInfo['materiel_first_class_name'],
                                'materiel_first_class_no' => $storageManageInfo['materiel_first_class_no'],
                                'materiel_class_id' => $storageManageInfo['materiel_class_id'],
                                'materiel_class_name' => $storageManageInfo['materiel_class_name'],
                                'materiel_class_no' => $storageManageInfo['materiel_class_no'],
                                'type_id' => $storageManageInfo['type_id'],
                                'materiel_name' => $storageManageInfo['materiel_name'],
                                'type_name' => $storageManageInfo['type_name'],
                                'materiel_no' => $storageManageInfo['materiel_no'],
                                'storage_id' => $storageManageInfo['storage_id'],
                                'storage_name' => $storageManageInfo['storage_name'],
                                'storage_address' => $storageManageInfo['storage_address'],
                                'storage_manage_id' => $storageManageInfo['storage_manage_id'],
                                'num' => $v3['num']
                            ]);
                        }
                    }
                }
            }

            DB::commit();
            return 1;
        } catch (\Exception $e) {
            Log::debug('同步套餐数据' . var_export($e->getMessage(), true));
            DB::rollBack();
            return ['code' => 1, 'msg' => $e->getMessage(), 'data' => null];
        }
    }

    /**
     * 同步库存中成本至物料商品表
     * AUTHOR  : Sun Wu
     * DateTime: 2022/6/6 16:17
     * @return bool
     */
    static public function syncMaterielCost($mainId, $batchTitle)
    {
        DB::beginTransaction();

        try {
            DB::enableQueryLog();
            $storageInfo = StorageManageModel::select(
                'id',
                'type_id',
                'materiel_mean_cost',
                'in_storage_num',
            )
                ->where('main_id', $mainId)
                ->orderBy('type_id', 'desc')
                ->get()->toArray();

            if (!empty($storageInfo)) {
                $batchInfo = [];
                $batchNo = $batchTitle . date('YmdHis', time()) . mt_rand(1000, 9999) . '0';
                $checkBatchInfo = StorageBatchModel::where('batch_no', $batchNo)->first();

                foreach ($storageInfo as $value) {
                    do {
                        $batchNo = $batchTitle . date('YmdHis', time()) . mt_rand(1000, 9999) . '0';
                    } while (!empty($checkBatchInfo));

                    $batchInfo[] = [
                        'batch_no' => $batchNo,
                        'storage_manage_id' => $value['id'],
                        'materiel_id' => 0,
                        'batch_num' => $value['in_storage_num'],
                        'batch_left_num' => $value['in_storage_num'],
                        'batch_cost' => $value['materiel_mean_cost'],
                        'main_id' => $mainId,
                        'created_at' => time()
                    ];

                    MaterielTypeModel::where('id', $value['type_id'])->update([
                        'cost' => $value['materiel_mean_cost']
                    ]);

                    StorageManageModel::where('id', $value['id'])
                        ->update([
                            'virtual_storage_num' => $value['in_storage_num']
                        ]);
                }

                StorageBatchModel::insert($batchInfo);
            }

            DB::commit();
            return true;
        } catch (\Exception $e) {
            DB::rollBack();
            Log::debug('同步成本异常：' . var_export($e->getMessage(), true));
            return false;
        }
    }

    public function syncSellTime()
    {
        DB::beginTransaction();

        try {
            $sellInfo = SellModel::select(
                'id',
                'sell_date'
            )
                ->get()->toArray();

            foreach ($sellInfo as $value) {
                SellModel::where('id', $value['id'])->update([
                    'sell_time' => strtotime(date('Y-m-d', strtotime($value['sell_date'])))
                ]);
            }

            DB::commit();
            return true;
        } catch (\Exception $e) {
            DB::rollBack();
            Log::debug('同步销售时间(仅保留年月日)异常' . var_export($e->getMessage(), true));
            return false;
        }
    }

    public function syncMaterielTime()
    {
        DB::beginTransaction();

        try {
            $materielInfo = MaterielModel::where(
                'purchase_time', '!=', 0
            )
                ->get()->toArray();

            foreach ($materielInfo as $value) {
                MaterielModel::where('id', $value['id'])
                    ->update([
                        'purchase_date' => strtotime(date('Y-m-d', strtotime($value['purchase_time'])))
                    ]);
            }
            DB::commit();
            return true;
        } catch (\Exception $e) {
            DB::rollBack();
            Log::debug('同步采购时间(仅保留年月日)异常' . var_export($e->getMessage(), true));
            return false;
        }
    }

    public function syncSupplier()
    {
        DB::beginTransaction();

        try {
            $info = SupplierCustomerModel::distinct()->orderBy('id', 'asc')->groupBy('user_id')->get()->toArray();

            foreach ($info as &$value) {
                $value['created_at'] = time();
                unset($value['id']);
            }

            SupplierCustomerModel::truncate();
            SupplierCustomerModel::insert($info);

            //绑定新的客户供应商id至采购或销售表内
            $materielInfo = MaterielModel::get()->toArray();
            $customerInfo = SupplierCustomerModel::get()->toArray();
            foreach ($materielInfo as $v) {
                foreach ($customerInfo as $v1) {
                    if ($v['supplier_name'] == $v1['name']) {
                        MaterielModel::where([
                            'main_id' => $v1['main_id'],
                            'supplier_name' => $v1['name']
                        ])->update(['supplier_customer_id' => $v1['id']]);
                    }
                }
            }

            $sellInfo = SellModel::get()->toArray();
            foreach ($sellInfo as $v2) {
                foreach ($customerInfo as $v3) {
                    if ($v2['customer_name'] == $v3['name']) {
                        SellModel::where([
                            'main_id' => $v3['main_id'],
                            'customer_name' => $v3['name']
                        ])->update(['customer_id' => $v3['id']]);
                    }
                }
            }

            $salesInfo = SalesReturnModel::get()->toArray();
            foreach ($salesInfo as $v4) {
                foreach ($customerInfo as $v5) {
                    if ($v4['customer_name'] == $v5['name']) {
                        SalesReturnModel::where([
                            'main_id' => $v5['main_id'],
                            'customer_name' => $v5['name']
                        ])->update(['customer_id' => $v5['id']]);
                    }
                }
            }

            DB::commit();
            return true;
        } catch (\Exception $e) {
            DB::rollBack();
            Log::debug('重置供应商客户表异常' . var_export($e->getMessage()));
            return false;
        }
    }

    /**
     * 同步当前成本至上一成本中
     * 前提：方便在采购单撤销时，对已经变动的成本金额进行回滚
     * AUTHOR  : Sun Wu
     * DateTime: 2022/7/22 14:44
     * @return boolean
     */
    public function syncCost()
    {
        ob_clean();
        set_time_limit(1800);
        $lineNum = 100;
        $count = MaterielTypeModel::where('delete_flag', 0)
            ->count();

        $totalPage = ceil($count / $lineNum);

        $i = 0;
        do {
            $materielInfo = MaterielTypeModel::select('id', 'cost')
                ->where('delete_flag', 0)
                ->where('cost', '!=', 0)
                ->offSet($i * $lineNum)->limit($lineNum)->get()->toArray();

            foreach ($materielInfo as $value) {
                MaterielTypeModel::where('id', $value['id'])->update([
                    'last_cost' => $value['cost']
                ]);
            }
            ++$i;
        } while ($i < $totalPage);

//        $allData = SELF::getAllData($totalPage, $lineNum);
//        $info = SELF::getInnerData($allData);
//
//        foreach($info as $value) {
//            var_dump($value);
////            MaterielsTypeModel::where('id', $value['id'])
////                ->update(['last_cost' => $value['cost']]);
//        }

        return true;
    }

    public function syncCost1()
    {
        ob_clean();
        set_time_limit(1800);

//        $info = LogOutStorageModel::select(
//            'a.id',
//            'materiel_type_id',
//            'cost'
//        )
//            ->from('log_outstorage as a')
//            ->leftJoin('materiel_type as b', 'b.id', '=', 'a.materiel_type_id')
//            ->where('is_cancel', 0)
//            ->where('all_id_type', 2)
//            ->get()->toArray();
        $info = LogOutStorageModel::select(
            'id',
            'materiel_type_id',
            'materiel_mean_cost'
        )
            ->from('log_outstorage')
            ->where('is_cancel', 0)
            ->where('all_id_type', 0)
            ->get()->toArray();

        DB::beginTransaction();
        try {
            foreach ($info as $value) {
                if ($value['materiel_mean_cost'] != 0) {
                    LogOutStorageModel::where('id', $value['id'])
                        ->update([
                            'sell_price' => $value['materiel_mean_cost'],
//                            'materiel_mean_cost' => $value['cost']
                        ]);
                }
            }
            DB::commit();
            return 1;
        } catch (\Exception $e) {
            DB::rollBack();
            return false;
        }
        return 1;
        var_dump($info);
        die;
        $materielInfo = SellGoodsDetailModel::select(
            'a.sell_id',
            'a.price',
            'b.id as type_id',
            'cost'
        )
            ->from('sell_goods_detail as a')
            ->leftJoin('materiel_type as b', 'b.id', '=', 'a.materiel_type_id')
            ->get()->toArray();

        $logInfo = LogOutStorageModel::where('is_cancel', 0)
            ->where('all_id_type', 2)
            ->get()->toArray();

        foreach ($materielInfo as $value) {
            if ($value['price'] != 0 && $value['cost'] != 0) {
                foreach ($logInfo as $val) {
                    LogOutStorageModel::where('all_id', $value['sell_id'])
                        ->update([
                            'sell_price' => $value['price'],
                            'materiel_mean_cost' => $value['cost']
                        ]);
                }
            }
        }

        return 1;
    }

    public function syncCost2()
    {
        $vipInfo = VipSettingModel::first();
        $adminInfo = AdminModel::select('id as main_id')->where([
            'parent_id' => 0,
            'delete_flag' => 0
        ])
            ->get()->toArray();

        foreach ($adminInfo as &$value) {
//            $value['is_vip'] = 0;
            $value['album_amount'] = $vipInfo['album_amount'];
            $value['album_page_amount'] = $vipInfo['album_page_amount'];
            $value['empty_bill_amount'] = $vipInfo['empty_bill_amount'];
            $value['special_seal'] = $vipInfo['special_seal'];
            $value['one_key_album_times'] = $vipInfo['one_key_album_times'];
            $value['express_check_times'] = $vipInfo['express_check_times'];
            $value['account_storage'] = $vipInfo['account_storage'];
            $value['clear_watermark_or_not'] = $vipInfo['clear_watermark_or_not'];
            $value['created_at'] = time();

        }

        AdminAddendumModel::insert($adminInfo);
        return true;
    }

    public function notVipMemberSyncInfo(){

        $vipInfo = VipSettingModel::first();

            $list = AdminAddendumModel::select('a.id as aid','main_id','account_storage','storage_end_date')
            ->from('admin_addendum as a')
            ->leftJoin('admin as b','b.id','=','a.main_id')
            ->where(['is_vip'=>0,'b.delete_flag'=>0,'account_storage'=>0])->get()->toArray();

            if(!empty($list)){
                $t=time()-365*24*3600;
                foreach ($list as $k=>$v){
                    if($v['account_storage'] == 0 && $v['storage_end_date'] == 0){//没有购买存储空间的
                        $account_storage = $vipInfo['account_storage'];
                    }else {
                            $spaceInfo = StorageSpaceOrderModel::
                            select(DB::raw('SUM(buy_storage_space) as totail_space'))->where(
                            [
                                'main_id'=>$v['main_id'],
                                'status'=>1,
                                'is_expire'=>0
                            ])->where('pay_time','<=',$t)->first()->toArray();

                            $account_storage = $vipInfo['account_storage'] + $spaceInfo['totail_space']*1024*1024;

                    }
                    $notVipArr[]=[
                        'id'=>$v['aid'],
                        'album_amount'           => $vipInfo['album_amount'],
                        'album_page_amount'      => $vipInfo['album_page_amount'],
                        'empty_bill_amount'      => $vipInfo['empty_bill_amount'],
                        'special_seal'           => $vipInfo['special_seal'],
                        'one_key_album_times'    => $vipInfo['one_key_album_times'],
                        'express_check_times'    => $vipInfo['express_check_times'],
                        'account_storage'        => $account_storage,
                        'clear_watermark_or_not' => $vipInfo['clear_watermark_or_not']
                    ];
                }

                batch()->update(new AdminAddendumModel(), $notVipArr, 'id');
            }


        return true;

    }
    public function setNewpwd()
    {
//        do {
//            $randNo = rand(000000, 999999);
//        }
//        while(!empty(AdminModel::where('parent_id', '!=', 0)
//            ->where([
//                'delete_flag' => 0,
//                'newpwd' => $randNo
//            ])->first()));

        $data = SELF::getUserInfo();
        foreach ($data as &$value) {
            switch (strlen($value['id'])) {
                case 1:
                    $value['newpwd'] = '00000' . $value['id'];
                    break;
                case 2:
                    $value['newpwd'] = '0000' . $value['id'];
                    break;
                case 3:
                    $value['newpwd'] = '000' . $value['id'];
                    break;
                case 4:
                    $value['newpwd'] = '00' . $value['id'];
                    break;
                case 5:
                    $value['newpwd'] = '0' . $value['id'];
                    break;
                case 6:
                    $value['newpwd'] = $value['id'];
                    break;
            }
        }

        batch()->update(new AdminModel, $data, 'id');
        return true;
    }

    //获取子账号信息
    public function getUserInfo()
    {
        return AdminModel::select('id')->where('delete_flag', 0)
            ->where('parent_id', '!=', 0)
            ->get()->toArray();
    }

    public function syncMaterielTypeImg()
    {
        $materielTypeInfo = MaterielTypeModel::select(
            'id', 'materiel_img as materiel_thumbnail_img'
        )->where('materiel_img', '!=', '')->where('delete_flag', 0)->get()->toArray();

        foreach($materielTypeInfo as &$value) {
            $value['materiel_thumbnail_img'] .= config('app.aliyun_oss_thumbnail_url');
        }

        DB::beginTransaction();

        try {
            batch()->update(new MaterielTypeModel, $materielTypeInfo, 'id');

            DB::commit();
            return true;
        }
        catch(\Exception $e) {
            DB::rollBack();
            return response()->json([
                'code' => 1,
                'msg' => $e->getMessage(),
                'data' => ''
            ]);
        }
    }

    public static function syncLocation()
    {
        set_time_limit(0);
//        $storage_list = StorageModel::select('*')->where(['delete_flag' => 0])->get()->toArray();
        $storageList = StorageModel::get()->toArray();

        $storageId = [];
        foreach($storageList as $value) {
            $storageId[] = $value['id'];
        }

        $storageLocation = StorageShelfLocationModel::get()->toArray();
        $locationId = [];
        foreach($storageLocation as $val) {
            $locationId[] = $val['storage_id'];
        }

        $withoutLocationStorageId = array_diff($storageId, $locationId);
        DB::beginTransaction();

        try {
            foreach ($withoutLocationStorageId as $k => $v) {
                $getStorageInfo = \App\Models\StorageModel::where('id', $v)->first();
                $shelf_obj = StorageShelfModel::updateOrCreate([
                    'storage_id' => $v,
                    'main_id' => $getStorageInfo['main_id'],
                    'status' => StorageShelfModel::USEDSTATUS,
                    'shelf_type' => StorageShelfModel::DEFAULTTYPE,
                ], [
                    'shelf_name' => '默认货架',
                    'main_id' => $getStorageInfo['main_id'],
                    'storage_id' => $v,
                    'status' => StorageShelfModel::USEDSTATUS,
                    'shelf_type' => StorageShelfModel::DEFAULTTYPE,

                ]);

                $shelf_id = $shelf_obj->id;

                $location_obj = StorageShelfLocationModel::updateOrCreate([
                    'storage_id' => $v,
                    'main_id' => $getStorageInfo['main_id'],
                    'shelf_id' => $shelf_id,
                    'status' => StorageShelfModel::USEDSTATUS,
                    'location_type' => StorageShelfLocationModel::DEFAULTTYPE,

                ], [
                    'location_name' => '默认库位',
                    'main_id' => $getStorageInfo['main_id'],
                    'storage_id' => $v,
                    'shelf_id' => $shelf_id,
                    'status' => StorageShelfModel::USEDSTATUS,
                    'location_type' => StorageShelfLocationModel::DEFAULTTYPE,

                ]);
            }

            DB::commit();
            return true;
        }
        catch(\Exception $e) {
            DB::rollBack();
            Log::debug('自动创建库位和货架异常');
            return false;
        }
    }

    public static function syncShelf()
    {
        $storageManageInfo = StorageManageModel::select(
            'a.id',
            'b.id as shelf_id',
            'c.id as location_id'
        )
            ->from('storage_manage as a')
            ->leftJoin('storage_shelf as b', 'b.storage_id', '=', 'a.storage_id')
            ->leftJoin('storage_shelf_location as c', 'c.shelf_id', '=', 'b.id')
            ->where([
//                'a.delete_flag' => 0,
                'a.shelf_id' => 0,
                'a.location_id' => 0,
                'location_type' => 1,
                'shelf_type' => 1,
            ])
            ->get()->toArray();

        DB::beginTransaction();

        try {
            if(!empty($storageManageInfo)) {
                batch()->update(new \App\Models\StorageManageModel, $storageManageInfo, 'id');
            }

            DB::commit();
            return true;
        }
        catch (\Exception $e) {
            DB::rollBack();
            Log::debug('自动同步库存货架及库位');
            return false;
        }
    }

    public function syncModule()
    {
        set_time_limit(0);
        ini_set('memory_limit', '1024M');
        $count = AdminModel::query()->where('parent_id', '!=', 0)
            ->where('delete_flag', 0)->count();

        $AdminInfo = AdminModel::query()->where('parent_id', '!=', 0)
//            ->where('id', 12429)
            ->where('delete_flag', 0)->get()->toArray();

        $decimal = ceil($count / 100);

        $i = 1;

        $firstModule = [];
        $secondModule = [];

        do {
            $adminSlice = array_slice($AdminInfo, $i *100, 100);

            foreach($adminSlice as $value) {
                if(!empty($value['first_module'])) {
                    $firstModuleArr = array_filter(explode(',', $value['first_module']), function($v) { return $v !== ''; });
                    foreach($firstModuleArr as $val) {
                        $firstModule[] = [
                            'main_id' => $value['parent_id'],
                            'user_id' => $value['id'],
                            'module_id' => $val,
                            'type' => 1,
                            'upper_module_id' =>0,
                            'created_at' => time()
                        ];
                    }
                }

                if(!empty($value['second_module'])) {
                    $secondModuleArr = array_filter(explode(',', $value['second_module']), function($v) { return $v !== ''; });
                    $moduleInfo = ModuleModel::whereIn('id', $secondModuleArr)->get()->toArray();

                    foreach($moduleInfo as $v) {
                        $secondModule[] = [
                            $value['parent_id'],
                            $value['id'],
                            $v['id'],
                            1,
                            $v['upper_module_id'],
                            time()
                        ];
                    }
                }
            }
            $i++;
        }
        while($i <= $decimal);

        DB::beginTransaction();
        try {
            $columns = [
                'main_id',
                'user_id',
                'module_id',
                'type',
                'upper_module_id',
                'created_at',
            ];

            $batchSize = 2000000;

//            AdminPermissionLimitModel::insert($firstModule);
            batch()->insert(new AdminPermissionLimitModel, $columns, $firstModule, $batchSize);
            batch()->insert(new AdminPermissionLimitModel, $columns, $secondModule, $batchSize);
            DB::commit();
            return true;
        }
        catch(\Exception $e) {
            Log::debug('同步子账号权限异常:'.var_export($e->getMessage(), true));
            DB::rollBack();
            return false;
        }
    }

    public function syncModule1()
    {
        $userInfo = AdminModel::query()->where('parent_id', '!=', 0)
            ->where('delete_flag', 0)
            ->get()->toArray();

        if(!empty($userInfo)) {
            echo count($userInfo);
            $i = 0;
//            $firstModule = [];
//            $secondModule = [];
//            foreach($userInfo as $value) {
//                if(!empty($value['first_module'])) {
//                    $firstModuleArr = array_filter(explode(',', $value['first_module']), function($v) { return $v !== ''; });
//                    foreach($firstModuleArr as $val) {
//                        $firstModule[] = [
//                            'main_id' => $value['parent_id'],
//                            'user_id' => $value['id'],
//                            'module_id' => $val,
//                            'created_at' => time()
//                        ];
//                    }
//                }
//
//                if(!empty($value['second_module'])) {
//                    $secondModuleArr = array_filter(explode(',', $value['second_module']), function($v) { return $v !== ''; });
//                    $moduleInfo = ModuleModel::whereIn('id', $secondModuleArr)->get()->toArray();
//
//                    foreach($moduleInfo as $v) {
//                        $secondModule[] = [
//                            'main_id' => $value['parent_id'],
//                            'user_id' => $value['id'],
//                            'module_id' => $v,
//                            'upper_module_id' => $v['upper_module_id'],
//                            'created_at' => time()
//                        ];
//                    }
//                }
//            }
//
//            var_dump($secondModule);die;
        }
    }

    public function syncTest13()
    {
        //获取已撤销的含有序列号的入库记录
        $logInstorageInfo = LogInStorageModel::where('is_cancel', 1)
            ->where('serial_number', '!=', '')
            ->get()->toArray();

        //组装被撤销的序列号信息
        $serialData = [];
        foreach($logInstorageInfo as $value) {
            $serialNumberInfo = array_filter(explode(',', $value['serial_number']), function($v) { return $v !== ''; });

            foreach($serialNumberInfo as $val) {
                $serialData[] = [
                    'goods_id' => $value['materiel_type_id'],
                    'serial_no' => $val
                ];
            }
        }

        //被撤销的序列号信息最后组装
        $data = [];
        foreach($serialData as $v) {
            //根据已撤销的序列号信息，查找当前已经被使用的序列号信息
            $serialInfo = SerialNumberModel::where([
                'goods_id' => $v['goods_id'],
                'serial_no' => $v['serial_no'],
                'status' => 0
            ])
                ->first();

            if(!empty($serialInfo)) {
                $data[] = $serialInfo['id'];
            }
        }

        //删除目标序列号
        SerialNumberModel::whereIn('id', array_unique($data))->delete();
        return true;
    }

    public function syncTest12()
    {
        $mainUserId = 12107;

        //获取直接入库未被撤销的序列号信息
        $assignInSerial = self::getInSerialData($mainUserId);

        //获取直接出库未被撤销的序列号信息
        $assignOutSerial = self::getOutSerialData($mainUserId);

        //获得出入库不重复的序列号id
        $arr = array_merge(array_diff($assignInSerial, $assignOutSerial), array_diff($assignOutSerial, $assignInSerial));

        //获取该账号下所有序列号
        $accountSerial = StorageManageModel::select('b.id', 'storage_manage.main_id')
            ->leftJoin('serial_number as b', 'b.storage_manage_id', '=', 'storage_manage.id')
            ->where('storage_manage.main_id', $mainUserId)->get()->toArray();

        $accountSerialArr = [];
        foreach($accountSerial as $val) {
            if(isset($val['id'])) {
                $accountSerialArr[] = $val['id'];
            }
        }

        //账号下所有序列号id和出入库不重复的序列号id的差集
        $rightSerial = array_merge(array_diff($arr, $accountSerialArr), array_diff($accountSerialArr, $arr));

        DB::beginTransaction();

        try {
            DB::enableQueryLog();
            StorageManageModel::from('storage_manage as a')
                ->leftJoin('serial_number as b', 'b.storage_manage_id', '=', 'a.id')
                ->where('a.main_id', $mainUserId)
                ->whereIn('b.id', $rightSerial)
                ->update([
                    'status' => 0
                ]);


            StorageManageModel::from('storage_manage as a')
                ->leftJoin('serial_number as b', 'b.storage_manage_id', '=', 'a.id')
                ->where('a.main_id', $mainUserId)
                ->whereNotIn('b.id', $rightSerial)
                ->update([
                    'status' => 1
                ]);

            $storageManageInfo = DB::select('
                SELECT storage_manage_id,count(*) AS c
                    FROM s_storage_manage AS a LEFT JOIN
                        s_serial_number AS b
                    ON a.id = b.storage_manage_id
                WHERE a.main_id = '.$mainUserId.' AND b.status = 1
                    GROUP BY b.storage_manage_id having c >= 1
            ');

            $storageManageEmpty = [];
            $storageManageUpdate = [];
            foreach($storageManageInfo as $v) {
                $storageManageEmpty[] = $v->storage_manage_id;

                $storageManageUpdate[] = [
                    'id' => $v->storage_manage_id,
                    'in_storage_num' => $v->c,
                    'virtual_storage_num' => $v->c,
                ];
            }

            if(!empty($storageManageUpdate)) {
                batch()->update(new StorageManageModel, $storageManageUpdate, 'id');
            }

            if(!empty($storageManageEmpty)) {
                StorageManageModel::whereNotIn('id', $storageManageEmpty)
                    ->update([
                        'in_storage_num' => 0,
                        'virtual_storage_num' => 0,
                    ]);
            }

            DB::commit();
            return true;
        }
        catch(\Exception $e) {
            Log::debug('同步序列号信息失败');
            DB::rollBack();
            return false;
        }
    }

    private function getOutSerialData($mainUserId)
    {
        //获取未被撤销的入库序列号信息
        $logOutCancelInfo = LogOutStorageModel::where([
            'main_id' => $mainUserId,
            'type' => 2,
            'is_cancel' => 0
        ])
            ->get()->toArray();

        if(empty($logInCancelInfo)) {
            return true;
        }

        $createTime = [];
        foreach($logOutCancelInfo as $value) {
            $createTime[] = strtotime($value['created_at']);
        }

        //已撤销的序列号信息
        $operateLog = OperationLogModel::where(
            'remark', '直接出库'
        )
            ->where('data', 'like', '%'.'serial_no'.'%')
            ->whereIn('created_at', $createTime)->get()->toArray();

        $outSerialData = [];
        foreach($operateLog as $val) {
            $dataContent = json_decode($val['data'], 'true');
            if(!empty($dataContent['goods_info'])) {
                $goodsInfo = json_decode($dataContent['goods_info'], true);
                foreach($goodsInfo as $v) {
                    if(!empty($v['serial_no'])) {
                        $storageManageInfo = StorageManageModel::where('id', $v['storageManageId'])->first();

                        $serialArr = array_filter(explode(',', $v['serial_no']), function($v) { return $v !== ''; });

                        $getSerailArr = [];
                        foreach($serialArr as $v1) {
                            $getSerailArr[] = $v1;
                        }

                        $serialInfo = SerialNumberModel::where([
                            'goods_id' => $storageManageInfo['type_id']
                        ])
                            ->whereIn('serial_no', $getSerailArr)->get()->toArray();

                        foreach($serialInfo as $v1) {
                            $outSerialData[] = $v1['id'];
                        }
                    }
                }
            }
        }

        return $outSerialData;
    }

    private function getInSerialData($mainUserId)
    {
        //获取未被撤销的入库序列号信息
        $logInCancelInfo = LogInStorageModel::where([
            'main_id' => $mainUserId,
            'type' => 2,
            'is_cancel' => 0
        ])
            ->get()->toArray();

        if(empty($logInCancelInfo)) {
            return true;
        }

        $createTime = [];
        foreach($logInCancelInfo as $value) {
            $createTime[] = strtotime($value['created_at']);
        }

        //已撤销的序列号信息
        $operateLog = OperationLogModel::where(
            'remark', '新建直接入库'
        )
            ->where('data', 'like', '%'.'serial_no'.'%')
            ->whereIn('created_at', $createTime)->get()->toArray();

        $inSerialData = [];
        foreach($operateLog as $val) {
            $dataContent = json_decode($val['data'], 'true');
            if(!empty($dataContent['goods_info'])) {
                $goodsInfo = json_decode($dataContent['goods_info'], true);
                foreach($goodsInfo as $v) {
                    if(!empty($v['serial_no'])) {

                        $serialArr = array_filter(explode(',', $v['serial_no']), function($v) { return $v !== ''; });

                        $getSerailArr = [];
                        foreach($serialArr as $v1) {
                            $getSerailArr[] = $v1;
                        }

                        $serialInfo = SerialNumberModel::whereIn('serial_no', $getSerailArr)->get()->toArray();


                        foreach($serialInfo as $v1) {
                            $inSerialData[] = $v1['id'];
                        }
                    }
                }
            }
        }

        return $inSerialData;
    }

    public function syncTest1()
    {
        $mainUserId = 12107;
        $storageManageInfo = DB::select('
            select id,type_id,`storage_id`,`location_id`,count(*) as c
                from s_storage_manage
                    where delete_flag = 0 and main_id = '.$mainUserId.'
                        group by type_id, location_id having c > 1
        ');

        $storageManageId = [];//被删除的库存id
        $updateStorageMangeInfo = [];//被更新的目标库存信息
        $inLogInfo = [];//要被重置的入库记录
        $outLogInfo = [];//要被重置的出库记录
        $serialInfo = [];//要被重置的序列号
        foreach($storageManageInfo as $value) {
            $getStorageManageInfo = StorageManageModel::where([
                'type_id' => $value->type_id,
                'storage_id' => $value->storage_id,
                'delete_flag' => 0
            ])
                ->orderBy('in_storage_num', 'desc')
                ->get()->toArray();

            $num = 0;
            foreach($getStorageManageInfo as $k => $val) {
                if($k != 0) {
                    $storageManageId[] = $getStorageManageInfo[0]['id'];
                    $num += $val['in_storage_num'];

                    //要被重置的入库记录
                    $resetLogInfo = LogInStorageModel::where([
                        'curr_storage_manage_id' => $val['id'],
                        'delete_flag' => 0
                    ])->get()->toArray();

                    foreach($resetLogInfo as $v) {
                        $inLogInfo[] = [
                            'id' => $v['id'],
                            'curr_storage_manage_id' => $getStorageManageInfo[0]['id'],
                            'old_in_storage_manage_id' => $v['curr_storage_manage_id'],
                        ];
                    }

                    //要被重置的出库记录
                    $resetLogInfo = LogOutStorageModel::where([
                        'curr_storage_manage_id' => $val['id'],
                        'delete_flag' => 0
                    ])->get()->toArray();

                    foreach($resetLogInfo as $v1) {
                        $outLogInfo[] = [
                            'id' => $v1['id'],
                            'curr_storage_manage_id' => $getStorageManageInfo[0]['id'],
                            'old_in_storage_manage_id' => $v1['curr_storage_manage_id'],
                        ];
                    }

                    //要被重置的序列号记录
                    $resetSerialInfo = SerialNumberModel::where([
                        'storage_manage_id' => $val['id'],
                    ])->get()->toArray();

                    foreach($resetSerialInfo as $v2) {
                        $serialInfo[] = [
                            'id' => $v2['id'],
                            'storage_manage_id' => $getStorageManageInfo[0]['id'],
                            'old_serial_storage_manage_id' => $v2['storage_manage_id'],
                        ];
                    }
                }
            }
            $updateStorageMangeInfo[] = [
                'id' => $getStorageManageInfo[0]['id'],
                'in_storage_num' => $getStorageManageInfo[0]['in_storage_num'] + $num,
                'virtual_storage_num' => $getStorageManageInfo[0]['virtual_storage_num'] + $num,
            ];
        }

        $storageManageId = array_values(array_unique($storageManageId));

        if(empty($storageManageId)) {
            return true;
        }

        DB::beginTransaction();

        try {
            $operateLogArr = [];
            StorageManageModel::whereIn('id', $storageManageId)->update([
                'delete_flag' => 1
            ]);

            $operateLogArr[] = [
                'main_id' => $mainUserId,
                'user_id' => $mainUserId,
                'remark' => '删除重复库存信息',
                'data' => json_encode($storageManageId),
                'created_at' => time(),
                'delete_flag' => 1,
                'ip' => $_SERVER["REMOTE_ADDR"]
            ];

            if(!empty($inLogInfo)) {
                $newInLogInfo = [];
                foreach($inLogInfo as $v3) {
                    $newInLogInfo[] = [
                        'id' => $v3['id'],
                        'curr_storage_manage_id' => $v3['curr_storage_manage_id']
                    ];
                }

                batch()->update(new LogInStorageModel, $newInLogInfo, 'id');

                $operateLogArr[] = [
                    'main_id' => $mainUserId,
                    'user_id' => $mainUserId,
                    'remark' => '删除重复入库信息',
                    'data' => json_encode($inLogInfo),
                    'created_at' => time(),
                    'delete_flag' => 1,
                    'ip' => $_SERVER["REMOTE_ADDR"]
                ];
            }

            if(!empty($outLogInfo)) {
                $newOutLogInfo = [];
                foreach($outLogInfo as $v4) {
                    $newOutLogInfo[] = [
                        'id' => $v4['id'],
                        'curr_storage_manage_id' => $v4['curr_storage_manage_id']
                    ];
                }

                batch()->update(new LogOutStorageModel, $newOutLogInfo, 'id');

                $operateLogArr[] = [
                    'main_id' => $mainUserId,
                    'user_id' => $mainUserId,
                    'remark' => '删除重复出库信息',
                    'data' => json_encode($outLogInfo),
                    'created_at' => time(),
                    'delete_flag' => 1,
                    'ip' => $_SERVER["REMOTE_ADDR"]
                ];
            }

            if(!empty($serialInfo)) {
                $newSerialInfo = [];
                foreach($serialInfo as $v5) {
                    $newSerialInfo[] = [
                        'id' => $v5['id'],
                        'storage_manage_id' => $v5['storage_manage_id']
                    ];
                }
                batch()->update(new SerialNumberModel, $newSerialInfo, 'id');

                $operateLogArr[] = [
                    'main_id' => $mainUserId,
                    'user_id' => $mainUserId,
                    'remark' => '删除重复序列号信息信息',
                    'data' => json_encode($serialInfo),
                    'created_at' => time(),
                    'delete_flag' => 1,
                    'ip' => $_SERVER["REMOTE_ADDR"]
                ];
            }

            OperationLogModel::insert($operateLogArr);
            DB::commit();
            return true;
        }
        catch(\Exception $e) {
            DB::rollBack();
            Log::debug('删除重复库存出错:'.var_export($e->getMessage(), true));
            return false;
        }
    }

    public function syncMaterielInfo($mainId = 11525)
    {
        $storageManageInfo = StorageManageModel::select(
            'a.id',
            'b.materiel_name',
            'b.type_name',
            'b.materiel_class_id'
        )
            ->from('storage_manage as a')
            ->leftJoin('materiel_type as b', 'b.id', '=', 'a.type_id')
            ->where('a.main_id', $mainId)
            ->get()->toArray();

        DB::beginTransaction();

        try {
            batch()->update(new StorageManageModel, $storageManageInfo, 'id');
            DB::commit();
            return true;
        }
        catch(\Exception $e) {
            DB::rollBack();
            return $e->getMessage();
        }
    }

}
